Natalie Adams and Matthew Haraden

For our final project, we plan to focus on the prevalence of grocery stores in Baltimore City. Food deserts are an issue in cities, especially in low income and minority areas. We want to look at how food deserts impact Baltimore.

Looking into grocery store data in Baltimore can help us determine if these stores are more accessible to people of a higher income versus people of a lower income. It can also help us see if there are any particular grocery stores that appear more often in higher income communities. The same goes for majority white and non-white majority neighborhoods. This data can be used to find possible discrepancies for grocery store locations in Baltimore.

Questions: How many grocery stores are in low income neighborhoods? How many grocery stores are in high income neighborhoods? How many grocery stores are in majority non-white neighborhoods? How many grocery stores are in majority white neighborhoods? How does this compare to convenience stores?

Things to Consider: How to define high and low income How to define majority white and non-majority white

Grocery Datasets: Supermarkets, Small Grocery Stores and Convenience Stores in Maryland https://data-clf.hub.arcgis.com/datasets/cce1f648db4b41acafdd66e45d8ad529_595/explore?location=38.803090%2C-77.248650%2C8.00&showTable=true

Income Datasets: https://vital-signs-bniajfi.hub.arcgis.com/datasets/bniajfi::median-household-income-community-statistical-area/explore?location=39.284832%2C-76.620524%2C12.52&showTable=true

Race Datasets: https://vital-signs-bniajfi.hub.arcgis.com/datasets/bniajfi::total-population/explore?layer=0&location=39.284832%2C-76.620524%2C12.52&showTable=true https://vital-signs-bniajfi.hub.arcgis.com/datasets/bniajfi::percent-of-residents-white-caucasian-non-hispanic-community-statistical-area-1/explore?location=39.284832%2C-76.620524%2C12.52 https://vital-signs-bniajfi.hub.arcgis.com/datasets/bniajfi::percent-of-residents-black-african-american-non-hispanic-community-statistical-area/explore?location=39.284832%2C-76.620524%2C12.52 ​​https://vital-signs-bniajfi.hub.arcgis.com/datasets/bniajfi::percent-of-residents-hispanic-community-statistical-area-1/explore?location=39.284832%2C-76.620524%2C12.52 https://vital-signs-bniajfi.hub.arcgis.com/datasets/percent-of-residents-asian-non-hispanic-community-statistical-area-1/explore?location=39.284832%2C-76.620524%2C12.52&showTable=true https://vital-signs-bniajfi.hub.arcgis.com/datasets/bniajfi::percent-of-residents-all-other-races-hawaiian-pacific-islander-alaskan-native-american-other-race-non-hispanic-community-statistical-area-1/explore?location=39.284832%2C-76.620524%2C12.52 https://vital-signs-bniajfi.hub.arcgis.com/datasets/bniajfi::percent-of-residents-two-or-more-races-non-hispanic-community-statistical-area-1/explore?location=39.284832%2C-76.620524%2C12.52

#load libraries

# turn off scientific notation
options(scipen=999)
# load libraries
library(janitor)

Attaching package: ‘janitor’

The following objects are masked from ‘package:stats’:

    chisq.test, fisher.test
library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ───────────────────────────────────────────── tidyverse 1.3.2 ──✔ ggplot2 3.3.6      ✔ purrr   0.3.4 
✔ tibble  3.1.8      ✔ dplyr   1.0.10
✔ tidyr   1.2.1      ✔ stringr 1.4.1 
✔ readr   2.1.2      ✔ forcats 0.5.2 ── Conflicts ──────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(sf)
Linking to GEOS 3.9.1, GDAL 3.4.3, PROJ 7.2.1; sf_use_s2() is TRUE
library(leaflet)
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
library(magrittr)

Attaching package: ‘magrittr’

The following object is masked from ‘package:purrr’:

    set_names

The following object is masked from ‘package:tidyr’:

    extract
library(ggplot2)

#load data Grocery store data comes from the Johns Hopkins Center for a Livable Future Open Data Portal and median household income and race data comes from the Baltimore Neighborhood Indicators Alliance Vital Signs Open Data Portal (see links above).

# food stores in maryland
stores <- read.csv("food_stores.csv")
# median household income by baltimore neighborhood
income <- read.csv("median_household_income.csv")
# baltimore neighborhoods shapefile
neighborhoods <- st_read("income_shapefiles/median_household_income.shp")
Reading layer `median_household_income' from data source 
  `C:\Users\mhara\Documents\GitHub\JOUR472\Final Project\income_shapefiles\median_household_income.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 55 features and 16 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 1393927 ymin: 557733.6 xmax: 1445503 ymax: 621406.8
Projected CRS: NAD83 / Maryland (ftUS)
# total population by baltimore neighborhood
total_pop1 <- read.csv("total_population.csv")
# white population by baltimore neighborhood
percent_white1 <- read.csv("percent_white.csv")
# black population by baltimore neighborhood
percent_black1 <- read.csv("percent_black.csv")
# hispanic population by baltimore neighborhood
percent_hispanic1 <- read.csv("percent_hispanic.csv")
# asian population by baltimore neighborhood
percent_asian1 <- read.csv("percent_asian.csv")
# other race population by baltimore neighborhood
percent_other1 <- read.csv("percent_other.csv")
# two or more races population by baltimore neighborhood
percent_more1 <- read.csv("percent_two_or_more.csv")
#baltimore population shapefile
population <- st_read("population_shapefiles/total_population.shp")
Reading layer `total_population' from data source 
  `C:\Users\mhara\Documents\GitHub\JOUR472\Final Project\population_shapefiles\total_population.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 55 features and 6 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 1393927 ymin: 557733.6 xmax: 1445503 ymax: 621406.8
Projected CRS: NAD83 / Maryland (ftUS)

#clean race data Cleaned the data to select just the neighborhood and 2020 population and then joined all the races together into one table. We did this because we couldn’t locate a single dataframe organized by race and neighborhood, so we combined separate ones and checked to make sure the percentages added up to 100.

# total population by baltimore neighborhood clean
total_pop2 <- total_pop1 %>% 
  select(CSA2010, tpop20) %>% 
  clean_names() %>%
  rename(neighborhood = 1, total_pop_2020 = 2)
# white population by baltimore neighborhood clean
percent_white2 <- percent_white1 %>% 
  select(CSA2010, pwhite20) %>% 
  clean_names() %>%
  rename(neighborhood = 1, percent_white = 2)
# black population by baltimore neighborhood clean
percent_black2 <- percent_black1 %>% 
  select(CSA2010, paa20) %>% 
  clean_names() %>%
  rename(neighborhood = 1, percent_black = 2)
# hispanic population by baltimore neighborhood clean
percent_hispanic2 <- percent_hispanic1 %>% 
  select(CSA2010, phisp20) %>% 
  clean_names() %>%
  rename(neighborhood = 1, percent_hispanic = 2)
# asian population by baltimore neighborhood clean
percent_asian2 <- percent_asian1 %>% 
  select(CSA2010, pasi20) %>% 
  clean_names() %>%
  rename(neighborhood = 1, percent_asian = 2)
# other race population by baltimore neighborhood clean
percent_other2 <- percent_other1 %>% 
  select(CSA2010, ppac20) %>% 
  clean_names() %>%
  rename(neighborhood = 1, percent_other = 2)
# two or more races population by baltimore neighborhood clean
percent_more2 <- percent_more1 %>% 
  select(CSA2010, p2more20) %>% 
  clean_names() %>%
  rename(neighborhood = 1, percent_two_or_more = 2)
# total baltimore population by race and baltimore neighborhood clean
baltimore_population <- total_pop2 %>% 
  inner_join(percent_white2, by="neighborhood") %>% 
  inner_join(percent_black2, by="neighborhood") %>% 
  inner_join(percent_hispanic2, by="neighborhood") %>% 
  inner_join(percent_asian2, by="neighborhood") %>% 
  inner_join(percent_other2, by="neighborhood") %>% 
  inner_join(percent_more2, by="neighborhood")

#clean grocery store data Selected relevant data points, filtered it for just the Baltimore City stores and cleaned column names. Made separate dataframes for supermarkets, small grocery stores and convenience stores.

# baltimore stores
baltimore_stores <- stores %>% 
  select(Main_Categ, Company_Na, County, Address, ZIP_Code, X, Y) %>% 
  filter(County == "Baltimore City") %>% 
  clean_names() %>%
  rename(store_type = 1, name = 2) %>% 
  st_as_sf(coords = c("x", "y"), crs = 4269) %>% 
  filter(store_type != "Public Market")
# baltimore supermarkets
supermarkets <- read_csv("food_stores.csv") %>% 
  select(Main_Categ, Company_Na, County, Address, ZIP_Code, X, Y) %>% 
  filter(County == "Baltimore City") %>% 
  clean_names() %>%
  rename(store_type = 1, name = 2) %>%
  filter(store_type == "Supermarket") %>% 
  st_as_sf(coords = c("x", "y"), crs = 4269)
Rows: 4690 Columns: 12── Column specification ──────────────────────────────────────────────────────────────
Delimiter: ","
chr (8): Main_Categ, Sub_Catego, Company_Na, Address, City, State, County, SNAP_Acc
dbl (4): X, Y, OBJECTID, ZIP_Code
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# baltimore small grocery stores
small_grocery <- read_csv("food_stores.csv") %>% 
  select(Main_Categ, Company_Na, County, Address, ZIP_Code, X, Y) %>% 
  filter(County == "Baltimore City") %>% 
  clean_names() %>%
  rename(store_type = 1, name = 2) %>%
  filter(store_type == "Small Grocery/Corner Store") %>% 
  st_as_sf(coords = c("x", "y"), crs = 4269)
Rows: 4690 Columns: 12── Column specification ──────────────────────────────────────────────────────────────
Delimiter: ","
chr (8): Main_Categ, Sub_Catego, Company_Na, Address, City, State, County, SNAP_Acc
dbl (4): X, Y, OBJECTID, ZIP_Code
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# baltimore convenience stores
convenience_stores <- read_csv("food_stores.csv") %>% 
  select(Main_Categ, Company_Na, County, Address, ZIP_Code, X, Y) %>% 
  filter(County == "Baltimore City") %>% 
  clean_names() %>%
  rename(store_type = 1, name = 2) %>%
  filter(store_type == "Convenience Store") %>% 
  st_as_sf(coords = c("x", "y"), crs = 4269)
Rows: 4690 Columns: 12── Column specification ──────────────────────────────────────────────────────────────
Delimiter: ","
chr (8): Main_Categ, Sub_Catego, Company_Na, Address, City, State, County, SNAP_Acc
dbl (4): X, Y, OBJECTID, ZIP_Code
ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

#clean median household income data and neighborhoods shapefile Selected most recent median household income data and cleaned column names.

The median household income in Baltimore is $52,164, according to the U.S. Census Bureau. This is less than the national median household income of $65,000. We chose to use the Baltimore median household income instead of the national median household income because it is more representative of the city. We defined low income as a median household income below Baltimore’s $52,164 median household income and high income as above that number. There are 32 neighborhoods characterized as low income and 23 neighborhoods characterized as high income.

# Load and clean low income neighborhood shapefile
low_income <- st_read("income_shapefiles/median_household_income.shp") %>% 
  clean_names() %>%
  select(csa2010, mhhi20, geometry) %>% 
  rename(neighborhood = 1, median_income=2) %>%
  mutate(
    income_level = case_when(
        median_income < 52164 ~ "low",
        median_income >= 52164 ~ "high"
      )
  ) %>% 
  filter(income_level == "low") %>%
  st_transform(crs=4269)
Reading layer `median_household_income' from data source 
  `C:\Users\mhara\Documents\GitHub\JOUR472\Final Project\income_shapefiles\median_household_income.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 55 features and 16 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 1393927 ymin: 557733.6 xmax: 1445503 ymax: 621406.8
Projected CRS: NAD83 / Maryland (ftUS)
# Load and clean high income neighborhood shapefile
high_income <- st_read("income_shapefiles/median_household_income.shp") %>% 
  clean_names() %>%
  select(csa2010, mhhi20, geometry) %>% 
  rename(neighborhood = 1, median_income=2) %>%
  mutate(
    income_level = case_when(
        median_income < 52164 ~ "low",
        median_income >= 52164 ~ "high"
      )
  ) %>% 
  filter(income_level == "high") %>%
  st_transform(crs=4269)
Reading layer `median_household_income' from data source 
  `C:\Users\mhara\Documents\GitHub\JOUR472\Final Project\income_shapefiles\median_household_income.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 55 features and 16 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 1393927 ymin: 557733.6 xmax: 1445503 ymax: 621406.8
Projected CRS: NAD83 / Maryland (ftUS)

#How does the number of supermarkets compare in low income and high income Baltimore neighborhoods? There are 25 supermarkets in low income neighborhoods and 24 supermarkets in high income neighborhoods. While low income neighborhoods have one more supermarket than high income neighborhoods, there are more low income neighborhoods (32) than high income neighborhoods (23), making the ratio of supermarkets to neighborhoods greater for high income neighborhoods. There are more than seven low income neighborhoods without a supermarket. Every high income neighborhood has a supermarket, plus an additional one. This shows that high income residents have greater access to supermarkets and fresh food than low income residents.

# sort coordinates into low income neighborhoods
low_income_supermarkets <- supermarkets %>%
  st_join(low_income) %>% 
  filter(income_level == "low")
# sort coordinates into high income neighborhoods
high_income_supermarkets <- supermarkets %>%
  st_join(high_income) %>% 
  filter(income_level == "high")

#plot supermarkets in baltimore based on income

ggplot()+
geom_sf(data=neighborhoods)+
geom_sf(data=low_income_supermarkets %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=income_level))+
geom_sf(data=high_income_supermarkets %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=income_level))+
theme_minimal()+
labs(title = "Supermarkets in High and Low Income Baltimore Neighborhoods", 
       subtitle = "Johns Hopkins and Baltimore Neighborhood Indicators Alliance Data, 2022",
       caption = "Graphic by Natalie Adams")

#How does the number of small grocery and corner stores compare in low income and high income Baltimore neighborhoods? There are 289 small grocery/corner stores in low income neighborhoods and 115 small grocery/corner stores in high income neighborhoods. Low income neighborhoods have more than twice as many small grocery/corner stores than high income neighborhoods and have a greater ratio of small grocery/corner stores than high income neighborhoods. Small grocery/corner stores typically offer ethnic or cultural food options, such as Asian or South American. The prevalence of small grocery/corner stores in low income neighborhoods indicates a possible high non-white population in those neighborhoods. Small grocery/corner stores could also make up for the absence of access to supermarkets in these communities, although access to fresh food could still be limited.

# sort coordinates into low income neighborhoods
low_income_small_grocery <- small_grocery %>%
  st_join(low_income) %>% 
  filter(income_level == "low")
# sort coordinates into high income neighborhoods
high_income_small_grocery <- small_grocery %>%
  st_join(high_income) %>% 
  filter(income_level == "high")

#plot small grocery stores in baltimore based on income

ggplot()+
geom_sf(data=neighborhoods)+
geom_sf(data=low_income_small_grocery %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=income_level))+
geom_sf(data=high_income_small_grocery %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=income_level))+
theme_minimal()+
labs(title = "Small Grocery and Corner Stores in High and Low Income Baltimore Neighborhoods", 
       subtitle = "Johns Hopkins and Baltimore Neighborhood Indicators Alliance Data, 2022",
       caption = "Graphic by Natalie Adams")

#How does the number of convenience stores compare in low income and high income Baltimore neighborhoods? There are 166 convenience stores in low income neighborhoods and 116 convenience stores in high income neighborhoods. The average number of convenience stores in low and high income neighborhoods is virtually the same (5.1 in low income compared to 5.0 in high income). Convenience stores typically have “junk food” and snacks, like chips, soda and candy. Large chain convenience stores, such as Royal Farms and Wawa, have options to order hot food, like fried chicken and sandwiches. Some convenience stores have fresh fruit, such as apples and bananas, but overall, do not offer great access to fresh food. While there is an equal percentage of convenience stores in high income and low income neighborhoods, the lower percentage of supermarkets in low income neighborhoods could indicate a stronger reliance on convenience stores for buying food.

# sort coordinates into low income neighborhoods
low_income_convenience_stores <- convenience_stores %>%
  st_join(low_income) %>% 
  filter(income_level == "low")
# sort coordinates into high income neighborhoods
high_income_convenience_stores <- convenience_stores %>%
  st_join(high_income) %>% 
  filter(income_level == "high")

#plot convenience stores in baltimore based on income

ggplot()+
geom_sf(data=neighborhoods)+
geom_sf(data=low_income_convenience_stores %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=income_level))+
geom_sf(data=high_income_convenience_stores %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=income_level))+
theme_minimal()+
labs(title = "Convenience Stores in High and Low Income Baltimore Neighborhoods", 
       subtitle = "Johns Hopkins and Baltimore Neighborhood Indicators Alliance Data, 2022",
       caption = "Graphic by Natalie Adams")

#clean race data and neighborhoods shapefile Selected white data and cleaned column names.

We defined majority white neighborhoods as neighborhoods with a neighborhood with a 50% or grater white population and non majority white neighborhoods as a neighborhood with a less than 50% white population. There are 11 majority white neighborhoods and 44 non majority white neighborhoods.

# filter for majority white neighborhoods
majority_white <- st_read("income_shapefiles/median_household_income.shp") %>% 
  clean_names() %>%
  select(csa2010, geometry) %>% 
  rename(neighborhood = 1) %>% 
  inner_join(percent_white2, by="neighborhood") %>% 
  mutate(
    population_status = case_when(
        percent_white < 50 ~ "non_majority_white",
        percent_white >= 50 ~ "majority_white"
      )
  ) %>%
  filter(population_status == "majority_white") %>%
  st_transform(crs=4269)
Reading layer `median_household_income' from data source 
  `C:\Users\mhara\Documents\GitHub\JOUR472\Final Project\income_shapefiles\median_household_income.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 55 features and 16 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 1393927 ymin: 557733.6 xmax: 1445503 ymax: 621406.8
Projected CRS: NAD83 / Maryland (ftUS)
# filter for non majority white neighborhoods
non_majority_white <- st_read("income_shapefiles/median_household_income.shp") %>% 
  clean_names() %>%
  select(csa2010, geometry) %>% 
  rename(neighborhood = 1) %>% 
  inner_join(percent_white2, by="neighborhood") %>% 
  mutate(
    population_status = case_when(
        percent_white < 50 ~ "non_majority_white",
        percent_white >= 50 ~ "majority_white"
      )
  ) %>%
  filter(population_status == "non_majority_white") %>%
  st_transform(crs=4269)
Reading layer `median_household_income' from data source 
  `C:\Users\mhara\Documents\GitHub\JOUR472\Final Project\income_shapefiles\median_household_income.shp' 
  using driver `ESRI Shapefile'
Simple feature collection with 55 features and 16 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 1393927 ymin: 557733.6 xmax: 1445503 ymax: 621406.8
Projected CRS: NAD83 / Maryland (ftUS)

#How does the number of supermarkets compare in majority white and non majority white Baltimore neighborhoods? There are 14 supermarkets in majority white neighborhoods and 35 supermarkets in non majority white neighborhoods. While non majority white neighborhoods have a higher number of supermarkets the ratio of supermarkets for majority white neighborhoods (14 supermarkets for 11 neighborhoods) is greater than the ratio of supermarkets for non majority white neighborhoods (35 supermarkets for 44 neighborhoods). This indicates that white residents have greater access to supermarkets and fresh food than non white residents.

# sort coordinates into majority white neighborhoods
majority_white_supermarkets <- supermarkets %>%
  st_join(majority_white) %>% 
  filter(population_status == "majority_white")
# sort coordinates into non majority white neighborhoods
non_majority_white_supermarkets <- supermarkets %>%
  st_join(non_majority_white) %>% 
  filter(population_status == "non_majority_white")

#plot supermarkets in baltimore based on race

ggplot()+
geom_sf(data=neighborhoods)+
geom_sf(data=majority_white_supermarkets %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=population_status))+
geom_sf(data=non_majority_white_supermarkets %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=population_status))+
theme_minimal()+
labs(title = "Supermarkets in Majority White and Non Majority White Baltimore Neighborhoods", 
       subtitle = "Johns Hopkins and Baltimore Neighborhood Indicators Alliance Data, 2022",
       caption = "Graphic by Natalie Adams")

#How does the number of small grocery and corner stores compare in majority white and non majority white Baltimore neighborhoods? There are 12 times as many small grocery/corner stores in non majority white neighborhoods (373) than majority white neighborhoods (31). Small grocery/corner stores typically offer ethnic or cultural food options, such as Asian or South American, so it makes sense for most of these stores to be in majority non white communities. It is unclear from this data whether the high number of small grocery/corner stores is due to preference of the neighborhood populations, a lack of access to other types of food stores (such as supermarkets), other factors or a combination of factors.

# sort coordinates into majority white neighborhoods
majority_white_small_grocery <- small_grocery %>%
  st_join(majority_white) %>% 
  filter(population_status == "majority_white")
# sort coordinates into non majority white neighborhoods
non_majority_white_small_grocery <- small_grocery %>%
  st_join(non_majority_white) %>% 
  filter(population_status == "non_majority_white")

#plot small grocery stores in baltimore based on race

ggplot()+
geom_sf(data=neighborhoods)+
geom_sf(data=majority_white_small_grocery %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=population_status))+
geom_sf(data=non_majority_white_small_grocery %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=population_status))+
theme_minimal()+
labs(title = "Small Grocery and Corner Stores in Majority White and Non Majority White Baltimore Neighborhoods", 
       subtitle = "Johns Hopkins and Baltimore Neighborhood Indicators Alliance Data, 2022",
       caption = "Graphic by Natalie Adams")

#How does the number of convenience stores compare in majority white and non majority white Baltimore neighborhoods? There are 49 convenience stores in majority white neighborhoods and 233 convenience stores in non majority white neighborhoods. The percentage of convenience stores in majority white and non majority white neighborhoods is nearly equal (4.5 in majority white compared to 5.3 in non majority white). Convenience stores typically have “junk food” and snacks, like chips, soda and candy. Large chain convenience stores, such as Royal Farms and Wawa, have options to order hot food, like fried chicken and sandwiches. Some convenience stores have fresh fruit, such as apples and bananas, but overall, do not offer great access to fresh food. While there is a nearly equal percentage of convenience stores in majority white and non majority white neighborhoods, the lower percentage of supermarkets in non majority white neighborhoods could indicate a stronger reliance on convenience stores for buying food.

# sort coordinates into majority white neighborhoods
majority_white_convenience_stores <- convenience_stores %>%
  st_join(majority_white) %>% 
  filter(population_status == "majority_white")
# sort coordinates into non majority white neighborhoods
non_majority_white_convenience_stores <- convenience_stores %>%
  st_join(non_majority_white) %>% 
  filter(population_status == "non_majority_white")

#plot convenience stores in baltimore based on race

ggplot()+
geom_sf(data=neighborhoods)+
geom_sf(data=majority_white_convenience_stores %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=population_status))+
geom_sf(data=non_majority_white_convenience_stores %>% st_as_sf(coords = c("x", "y"), crs = 4326), mapping=aes(color=population_status))+
theme_minimal()+
labs(title = "Convenience Stores in Majority White and Non Majority White Baltimore Neighborhoods", 
       subtitle = "Johns Hopkins and Baltimore Neighborhood Indicators Alliance Data, 2022",
       caption = "Graphic by Natalie Adams")

#leaflet race graph The neighborhoods highlighted in yellow represent those with a majority white population. The neighborhoods in blue have a majority non-white population. A work in progress, more to come.

pal <- colorFactor(
  palette = c('red', 'darkgreen', 'black'),
  domain = baltimore_stores$store_type
)

leaflet() %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addPolygons(data=majority_white,
              color = ("#fbd009"),
              weight = 1.5,
              smoothFactor = 0.2,
              fillOpacity = 0.1,
              label = majority_white$neighborhood) %>% 
  addPolygons(data=non_majority_white,
              color = ("#199bd6"),
              weight = 1.5,
              smoothFactor = 0.2,
              fillOpacity = 0.1,
              label = non_majority_white$neighborhood) %>%
  addCircles(data=baltimore_stores,
             weight = 2,
             color = ~pal(store_type),
             label= paste("Store Name:",baltimore_stores$name, "Store Type:", baltimore_stores$store_type)) %>% 
    addLegend(
   position = "bottomright",
    pal = pal,
    values = baltimore_stores$store_type,
    title = "Baltimore Stores by Type"
  )
Warning: sf layer has inconsistent datum (+proj=longlat +datum=NAD83 +no_defs).
Need '+proj=longlat +datum=WGS84'Warning: sf layer has inconsistent datum (+proj=longlat +datum=NAD83 +no_defs).
Need '+proj=longlat +datum=WGS84'Warning: sf layer has inconsistent datum (+proj=longlat +datum=NAD83 +no_defs).
Need '+proj=longlat +datum=WGS84'

#Income Leaflet Graph The neighborhoods with a low income are highlighted in yellow and neighborhoods with high incomes are highlighted in blue.

pal <- colorFactor(
  palette = c('red', 'darkgreen', 'black'),
  domain = baltimore_stores$store_type
)
leaflet() %>%
  addProviderTiles(providers$CartoDB.Positron) %>%
  addPolygons(data=low_income,
              color = ("#199bd6"),
              weight = 1.5,
              smoothFactor = 0.2,
              fillOpacity = 0.1,
              label = majority_white$neighborhood) %>% 
  addPolygons(data=high_income,
              color = ("#fbd009"),
              weight = 1.5,
              smoothFactor = 0.2,
              fillOpacity = 0.1,
              label = non_majority_white$neighborhood) %>%
  addCircles(data=baltimore_stores,
             weight = 2,
             color = ~pal(store_type),
             label= paste("Store Name:",baltimore_stores$name, "Store Type:", baltimore_stores$store_type)) %>% 
    addLegend(
   position = "bottomright",
    pal = pal,
    values = baltimore_stores$store_type,
    title = "Baltimore Stores by Type"
  )
Warning: sf layer has inconsistent datum (+proj=longlat +datum=NAD83 +no_defs).
Need '+proj=longlat +datum=WGS84'Warning: sf layer has inconsistent datum (+proj=longlat +datum=NAD83 +no_defs).
Need '+proj=longlat +datum=WGS84'Warning: sf layer has inconsistent datum (+proj=longlat +datum=NAD83 +no_defs).
Need '+proj=longlat +datum=WGS84'
LS0tDQp0aXRsZTogIkJhbHRpbW9yZV9Gb29kX0Rlc2VydCINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCk5hdGFsaWUgQWRhbXMgYW5kIE1hdHRoZXcgSGFyYWRlbg0KDQpGb3Igb3VyIGZpbmFsIHByb2plY3QsIHdlIHBsYW4gdG8gZm9jdXMgb24gdGhlIHByZXZhbGVuY2Ugb2YgZ3JvY2VyeSBzdG9yZXMgaW4gQmFsdGltb3JlIENpdHkuIEZvb2QgZGVzZXJ0cyBhcmUgYW4gaXNzdWUgaW4gY2l0aWVzLCBlc3BlY2lhbGx5IGluIGxvdyBpbmNvbWUgYW5kIG1pbm9yaXR5IGFyZWFzLiBXZSB3YW50IHRvIGxvb2sgYXQgaG93IGZvb2QgZGVzZXJ0cyBpbXBhY3QgQmFsdGltb3JlLg0KDQpMb29raW5nIGludG8gZ3JvY2VyeSBzdG9yZSBkYXRhIGluIEJhbHRpbW9yZSBjYW4gaGVscCB1cyBkZXRlcm1pbmUgaWYgdGhlc2Ugc3RvcmVzIGFyZSBtb3JlIGFjY2Vzc2libGUgdG8gcGVvcGxlIG9mIGEgaGlnaGVyIGluY29tZSB2ZXJzdXMgcGVvcGxlIG9mIGEgbG93ZXIgaW5jb21lLiBJdCBjYW4gYWxzbyBoZWxwIHVzIHNlZSBpZiB0aGVyZSBhcmUgYW55IHBhcnRpY3VsYXIgZ3JvY2VyeSBzdG9yZXMgdGhhdCBhcHBlYXIgbW9yZSBvZnRlbiBpbiBoaWdoZXIgaW5jb21lIGNvbW11bml0aWVzLiBUaGUgc2FtZSBnb2VzIGZvciBtYWpvcml0eSB3aGl0ZSBhbmQgbm9uLXdoaXRlIG1ham9yaXR5IG5laWdoYm9yaG9vZHMuIFRoaXMgZGF0YSBjYW4gYmUgdXNlZCB0byBmaW5kIHBvc3NpYmxlIGRpc2NyZXBhbmNpZXMgZm9yIGdyb2Nlcnkgc3RvcmUgbG9jYXRpb25zIGluIEJhbHRpbW9yZS4NCg0KUXVlc3Rpb25zOg0KSG93IG1hbnkgZ3JvY2VyeSBzdG9yZXMgYXJlIGluIGxvdyBpbmNvbWUgbmVpZ2hib3Job29kcz8NCkhvdyBtYW55IGdyb2Nlcnkgc3RvcmVzIGFyZSBpbiBoaWdoIGluY29tZSBuZWlnaGJvcmhvb2RzPw0KSG93IG1hbnkgZ3JvY2VyeSBzdG9yZXMgYXJlIGluIG1ham9yaXR5IG5vbi13aGl0ZSBuZWlnaGJvcmhvb2RzPw0KSG93IG1hbnkgZ3JvY2VyeSBzdG9yZXMgYXJlIGluIG1ham9yaXR5IHdoaXRlIG5laWdoYm9yaG9vZHM/DQpIb3cgZG9lcyB0aGlzIGNvbXBhcmUgdG8gY29udmVuaWVuY2Ugc3RvcmVzPw0KDQpUaGluZ3MgdG8gQ29uc2lkZXI6DQpIb3cgdG8gZGVmaW5lIGhpZ2ggYW5kIGxvdyBpbmNvbWUNCkhvdyB0byBkZWZpbmUgbWFqb3JpdHkgd2hpdGUgYW5kIG5vbi1tYWpvcml0eSB3aGl0ZQ0KDQpHcm9jZXJ5IERhdGFzZXRzOiANClN1cGVybWFya2V0cywgU21hbGwgR3JvY2VyeSBTdG9yZXMgYW5kIENvbnZlbmllbmNlIFN0b3JlcyBpbiBNYXJ5bGFuZA0KaHR0cHM6Ly9kYXRhLWNsZi5odWIuYXJjZ2lzLmNvbS9kYXRhc2V0cy9jY2UxZjY0OGRiNGI0MWFjYWZkZDY2ZTQ1ZDhhZDUyOV81OTUvZXhwbG9yZT9sb2NhdGlvbj0zOC44MDMwOTAlMkMtNzcuMjQ4NjUwJTJDOC4wMCZzaG93VGFibGU9dHJ1ZSANCg0KSW5jb21lIERhdGFzZXRzOg0KaHR0cHM6Ly92aXRhbC1zaWducy1ibmlhamZpLmh1Yi5hcmNnaXMuY29tL2RhdGFzZXRzL2JuaWFqZmk6Om1lZGlhbi1ob3VzZWhvbGQtaW5jb21lLWNvbW11bml0eS1zdGF0aXN0aWNhbC1hcmVhL2V4cGxvcmU/bG9jYXRpb249MzkuMjg0ODMyJTJDLTc2LjYyMDUyNCUyQzEyLjUyJnNob3dUYWJsZT10cnVlDQoNClJhY2UgRGF0YXNldHM6DQpodHRwczovL3ZpdGFsLXNpZ25zLWJuaWFqZmkuaHViLmFyY2dpcy5jb20vZGF0YXNldHMvYm5pYWpmaTo6dG90YWwtcG9wdWxhdGlvbi9leHBsb3JlP2xheWVyPTAmbG9jYXRpb249MzkuMjg0ODMyJTJDLTc2LjYyMDUyNCUyQzEyLjUyJnNob3dUYWJsZT10cnVlDQpodHRwczovL3ZpdGFsLXNpZ25zLWJuaWFqZmkuaHViLmFyY2dpcy5jb20vZGF0YXNldHMvYm5pYWpmaTo6cGVyY2VudC1vZi1yZXNpZGVudHMtd2hpdGUtY2F1Y2FzaWFuLW5vbi1oaXNwYW5pYy1jb21tdW5pdHktc3RhdGlzdGljYWwtYXJlYS0xL2V4cGxvcmU/bG9jYXRpb249MzkuMjg0ODMyJTJDLTc2LjYyMDUyNCUyQzEyLjUyDQpodHRwczovL3ZpdGFsLXNpZ25zLWJuaWFqZmkuaHViLmFyY2dpcy5jb20vZGF0YXNldHMvYm5pYWpmaTo6cGVyY2VudC1vZi1yZXNpZGVudHMtYmxhY2stYWZyaWNhbi1hbWVyaWNhbi1ub24taGlzcGFuaWMtY29tbXVuaXR5LXN0YXRpc3RpY2FsLWFyZWEvZXhwbG9yZT9sb2NhdGlvbj0zOS4yODQ4MzIlMkMtNzYuNjIwNTI0JTJDMTIuNTINCuKAi+KAi2h0dHBzOi8vdml0YWwtc2lnbnMtYm5pYWpmaS5odWIuYXJjZ2lzLmNvbS9kYXRhc2V0cy9ibmlhamZpOjpwZXJjZW50LW9mLXJlc2lkZW50cy1oaXNwYW5pYy1jb21tdW5pdHktc3RhdGlzdGljYWwtYXJlYS0xL2V4cGxvcmU/bG9jYXRpb249MzkuMjg0ODMyJTJDLTc2LjYyMDUyNCUyQzEyLjUyDQpodHRwczovL3ZpdGFsLXNpZ25zLWJuaWFqZmkuaHViLmFyY2dpcy5jb20vZGF0YXNldHMvcGVyY2VudC1vZi1yZXNpZGVudHMtYXNpYW4tbm9uLWhpc3BhbmljLWNvbW11bml0eS1zdGF0aXN0aWNhbC1hcmVhLTEvZXhwbG9yZT9sb2NhdGlvbj0zOS4yODQ4MzIlMkMtNzYuNjIwNTI0JTJDMTIuNTImc2hvd1RhYmxlPXRydWUNCmh0dHBzOi8vdml0YWwtc2lnbnMtYm5pYWpmaS5odWIuYXJjZ2lzLmNvbS9kYXRhc2V0cy9ibmlhamZpOjpwZXJjZW50LW9mLXJlc2lkZW50cy1hbGwtb3RoZXItcmFjZXMtaGF3YWlpYW4tcGFjaWZpYy1pc2xhbmRlci1hbGFza2FuLW5hdGl2ZS1hbWVyaWNhbi1vdGhlci1yYWNlLW5vbi1oaXNwYW5pYy1jb21tdW5pdHktc3RhdGlzdGljYWwtYXJlYS0xL2V4cGxvcmU/bG9jYXRpb249MzkuMjg0ODMyJTJDLTc2LjYyMDUyNCUyQzEyLjUyDQpodHRwczovL3ZpdGFsLXNpZ25zLWJuaWFqZmkuaHViLmFyY2dpcy5jb20vZGF0YXNldHMvYm5pYWpmaTo6cGVyY2VudC1vZi1yZXNpZGVudHMtdHdvLW9yLW1vcmUtcmFjZXMtbm9uLWhpc3BhbmljLWNvbW11bml0eS1zdGF0aXN0aWNhbC1hcmVhLTEvZXhwbG9yZT9sb2NhdGlvbj0zOS4yODQ4MzIlMkMtNzYuNjIwNTI0JTJDMTIuNTINCg0KI2xvYWQgbGlicmFyaWVzDQpgYGB7cn0NCiMgdHVybiBvZmYgc2NpZW50aWZpYyBub3RhdGlvbg0Kb3B0aW9ucyhzY2lwZW49OTk5KQ0KIyBsb2FkIGxpYnJhcmllcw0KbGlicmFyeShqYW5pdG9yKQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNmKQ0KbGlicmFyeShsZWFmbGV0KQ0KbGlicmFyeShtYWdyaXR0cikNCmxpYnJhcnkoZ2dwbG90MikNCmBgYA0KDQojbG9hZCBkYXRhDQpHcm9jZXJ5IHN0b3JlIGRhdGEgY29tZXMgZnJvbSB0aGUgSm9obnMgSG9wa2lucyBDZW50ZXIgZm9yIGEgTGl2YWJsZSBGdXR1cmUgT3BlbiBEYXRhIFBvcnRhbCBhbmQgbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUgYW5kIHJhY2UgZGF0YSBjb21lcyBmcm9tIHRoZSBCYWx0aW1vcmUgTmVpZ2hib3Job29kIEluZGljYXRvcnMgQWxsaWFuY2UgVml0YWwgU2lnbnMgT3BlbiBEYXRhIFBvcnRhbCAoc2VlIGxpbmtzIGFib3ZlKS4NCg0KYGBge3J9DQojIGZvb2Qgc3RvcmVzIGluIG1hcnlsYW5kDQpzdG9yZXMgPC0gcmVhZC5jc3YoImZvb2Rfc3RvcmVzLmNzdiIpDQojIG1lZGlhbiBob3VzZWhvbGQgaW5jb21lIGJ5IGJhbHRpbW9yZSBuZWlnaGJvcmhvb2QNCmluY29tZSA8LSByZWFkLmNzdigibWVkaWFuX2hvdXNlaG9sZF9pbmNvbWUuY3N2IikNCiMgYmFsdGltb3JlIG5laWdoYm9yaG9vZHMgc2hhcGVmaWxlDQpuZWlnaGJvcmhvb2RzIDwtIHN0X3JlYWQoImluY29tZV9zaGFwZWZpbGVzL21lZGlhbl9ob3VzZWhvbGRfaW5jb21lLnNocCIpDQojIHRvdGFsIHBvcHVsYXRpb24gYnkgYmFsdGltb3JlIG5laWdoYm9yaG9vZA0KdG90YWxfcG9wMSA8LSByZWFkLmNzdigidG90YWxfcG9wdWxhdGlvbi5jc3YiKQ0KIyB3aGl0ZSBwb3B1bGF0aW9uIGJ5IGJhbHRpbW9yZSBuZWlnaGJvcmhvb2QNCnBlcmNlbnRfd2hpdGUxIDwtIHJlYWQuY3N2KCJwZXJjZW50X3doaXRlLmNzdiIpDQojIGJsYWNrIHBvcHVsYXRpb24gYnkgYmFsdGltb3JlIG5laWdoYm9yaG9vZA0KcGVyY2VudF9ibGFjazEgPC0gcmVhZC5jc3YoInBlcmNlbnRfYmxhY2suY3N2IikNCiMgaGlzcGFuaWMgcG9wdWxhdGlvbiBieSBiYWx0aW1vcmUgbmVpZ2hib3Job29kDQpwZXJjZW50X2hpc3BhbmljMSA8LSByZWFkLmNzdigicGVyY2VudF9oaXNwYW5pYy5jc3YiKQ0KIyBhc2lhbiBwb3B1bGF0aW9uIGJ5IGJhbHRpbW9yZSBuZWlnaGJvcmhvb2QNCnBlcmNlbnRfYXNpYW4xIDwtIHJlYWQuY3N2KCJwZXJjZW50X2FzaWFuLmNzdiIpDQojIG90aGVyIHJhY2UgcG9wdWxhdGlvbiBieSBiYWx0aW1vcmUgbmVpZ2hib3Job29kDQpwZXJjZW50X290aGVyMSA8LSByZWFkLmNzdigicGVyY2VudF9vdGhlci5jc3YiKQ0KIyB0d28gb3IgbW9yZSByYWNlcyBwb3B1bGF0aW9uIGJ5IGJhbHRpbW9yZSBuZWlnaGJvcmhvb2QNCnBlcmNlbnRfbW9yZTEgPC0gcmVhZC5jc3YoInBlcmNlbnRfdHdvX29yX21vcmUuY3N2IikNCiNiYWx0aW1vcmUgcG9wdWxhdGlvbiBzaGFwZWZpbGUNCnBvcHVsYXRpb24gPC0gc3RfcmVhZCgicG9wdWxhdGlvbl9zaGFwZWZpbGVzL3RvdGFsX3BvcHVsYXRpb24uc2hwIikNCmBgYA0KDQojY2xlYW4gcmFjZSBkYXRhDQpDbGVhbmVkIHRoZSBkYXRhIHRvIHNlbGVjdCBqdXN0IHRoZSBuZWlnaGJvcmhvb2QgYW5kIDIwMjAgcG9wdWxhdGlvbiBhbmQgdGhlbiBqb2luZWQgYWxsIHRoZSByYWNlcyB0b2dldGhlciBpbnRvIG9uZSB0YWJsZS4gV2UgZGlkIHRoaXMgYmVjYXVzZSB3ZSBjb3VsZG4ndCBsb2NhdGUgYSBzaW5nbGUgZGF0YWZyYW1lIG9yZ2FuaXplZCBieSByYWNlIGFuZCBuZWlnaGJvcmhvb2QsIHNvIHdlIGNvbWJpbmVkIHNlcGFyYXRlIG9uZXMgYW5kIGNoZWNrZWQgdG8gbWFrZSBzdXJlIHRoZSBwZXJjZW50YWdlcyBhZGRlZCB1cCB0byAxMDAuDQoNCmBgYHtyfQ0KIyB0b3RhbCBwb3B1bGF0aW9uIGJ5IGJhbHRpbW9yZSBuZWlnaGJvcmhvb2QgY2xlYW4NCnRvdGFsX3BvcDIgPC0gdG90YWxfcG9wMSAlPiUgDQogIHNlbGVjdChDU0EyMDEwLCB0cG9wMjApICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUNCiAgcmVuYW1lKG5laWdoYm9yaG9vZCA9IDEsIHRvdGFsX3BvcF8yMDIwID0gMikNCiMgd2hpdGUgcG9wdWxhdGlvbiBieSBiYWx0aW1vcmUgbmVpZ2hib3Job29kIGNsZWFuDQpwZXJjZW50X3doaXRlMiA8LSBwZXJjZW50X3doaXRlMSAlPiUgDQogIHNlbGVjdChDU0EyMDEwLCBwd2hpdGUyMCkgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JQ0KICByZW5hbWUobmVpZ2hib3Job29kID0gMSwgcGVyY2VudF93aGl0ZSA9IDIpDQojIGJsYWNrIHBvcHVsYXRpb24gYnkgYmFsdGltb3JlIG5laWdoYm9yaG9vZCBjbGVhbg0KcGVyY2VudF9ibGFjazIgPC0gcGVyY2VudF9ibGFjazEgJT4lIA0KICBzZWxlY3QoQ1NBMjAxMCwgcGFhMjApICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUNCiAgcmVuYW1lKG5laWdoYm9yaG9vZCA9IDEsIHBlcmNlbnRfYmxhY2sgPSAyKQ0KIyBoaXNwYW5pYyBwb3B1bGF0aW9uIGJ5IGJhbHRpbW9yZSBuZWlnaGJvcmhvb2QgY2xlYW4NCnBlcmNlbnRfaGlzcGFuaWMyIDwtIHBlcmNlbnRfaGlzcGFuaWMxICU+JSANCiAgc2VsZWN0KENTQTIwMTAsIHBoaXNwMjApICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUNCiAgcmVuYW1lKG5laWdoYm9yaG9vZCA9IDEsIHBlcmNlbnRfaGlzcGFuaWMgPSAyKQ0KIyBhc2lhbiBwb3B1bGF0aW9uIGJ5IGJhbHRpbW9yZSBuZWlnaGJvcmhvb2QgY2xlYW4NCnBlcmNlbnRfYXNpYW4yIDwtIHBlcmNlbnRfYXNpYW4xICU+JSANCiAgc2VsZWN0KENTQTIwMTAsIHBhc2kyMCkgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JQ0KICByZW5hbWUobmVpZ2hib3Job29kID0gMSwgcGVyY2VudF9hc2lhbiA9IDIpDQojIG90aGVyIHJhY2UgcG9wdWxhdGlvbiBieSBiYWx0aW1vcmUgbmVpZ2hib3Job29kIGNsZWFuDQpwZXJjZW50X290aGVyMiA8LSBwZXJjZW50X290aGVyMSAlPiUgDQogIHNlbGVjdChDU0EyMDEwLCBwcGFjMjApICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUNCiAgcmVuYW1lKG5laWdoYm9yaG9vZCA9IDEsIHBlcmNlbnRfb3RoZXIgPSAyKQ0KIyB0d28gb3IgbW9yZSByYWNlcyBwb3B1bGF0aW9uIGJ5IGJhbHRpbW9yZSBuZWlnaGJvcmhvb2QgY2xlYW4NCnBlcmNlbnRfbW9yZTIgPC0gcGVyY2VudF9tb3JlMSAlPiUgDQogIHNlbGVjdChDU0EyMDEwLCBwMm1vcmUyMCkgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JQ0KICByZW5hbWUobmVpZ2hib3Job29kID0gMSwgcGVyY2VudF90d29fb3JfbW9yZSA9IDIpDQojIHRvdGFsIGJhbHRpbW9yZSBwb3B1bGF0aW9uIGJ5IHJhY2UgYW5kIGJhbHRpbW9yZSBuZWlnaGJvcmhvb2QgY2xlYW4NCmJhbHRpbW9yZV9wb3B1bGF0aW9uIDwtIHRvdGFsX3BvcDIgJT4lIA0KICBpbm5lcl9qb2luKHBlcmNlbnRfd2hpdGUyLCBieT0ibmVpZ2hib3Job29kIikgJT4lIA0KICBpbm5lcl9qb2luKHBlcmNlbnRfYmxhY2syLCBieT0ibmVpZ2hib3Job29kIikgJT4lIA0KICBpbm5lcl9qb2luKHBlcmNlbnRfaGlzcGFuaWMyLCBieT0ibmVpZ2hib3Job29kIikgJT4lIA0KICBpbm5lcl9qb2luKHBlcmNlbnRfYXNpYW4yLCBieT0ibmVpZ2hib3Job29kIikgJT4lIA0KICBpbm5lcl9qb2luKHBlcmNlbnRfb3RoZXIyLCBieT0ibmVpZ2hib3Job29kIikgJT4lIA0KICBpbm5lcl9qb2luKHBlcmNlbnRfbW9yZTIsIGJ5PSJuZWlnaGJvcmhvb2QiKQ0KYGBgDQoNCiNjbGVhbiBncm9jZXJ5IHN0b3JlIGRhdGENClNlbGVjdGVkIHJlbGV2YW50IGRhdGEgcG9pbnRzLCBmaWx0ZXJlZCBpdCBmb3IganVzdCB0aGUgQmFsdGltb3JlIENpdHkgc3RvcmVzIGFuZCBjbGVhbmVkIGNvbHVtbiBuYW1lcy4gTWFkZSBzZXBhcmF0ZSBkYXRhZnJhbWVzIGZvciBzdXBlcm1hcmtldHMsIHNtYWxsIGdyb2Nlcnkgc3RvcmVzIGFuZCBjb252ZW5pZW5jZSBzdG9yZXMuDQoNCmBgYHtyfQ0KIyBiYWx0aW1vcmUgc3RvcmVzDQpiYWx0aW1vcmVfc3RvcmVzIDwtIHN0b3JlcyAlPiUgDQogIHNlbGVjdChNYWluX0NhdGVnLCBDb21wYW55X05hLCBDb3VudHksIEFkZHJlc3MsIFpJUF9Db2RlLCBYLCBZKSAlPiUgDQogIGZpbHRlcihDb3VudHkgPT0gIkJhbHRpbW9yZSBDaXR5IikgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JQ0KICByZW5hbWUoc3RvcmVfdHlwZSA9IDEsIG5hbWUgPSAyKSAlPiUgDQogIHN0X2FzX3NmKGNvb3JkcyA9IGMoIngiLCAieSIpLCBjcnMgPSA0MjY5KSAlPiUgDQogIGZpbHRlcihzdG9yZV90eXBlICE9ICJQdWJsaWMgTWFya2V0IikNCiMgYmFsdGltb3JlIHN1cGVybWFya2V0cw0Kc3VwZXJtYXJrZXRzIDwtIHJlYWRfY3N2KCJmb29kX3N0b3Jlcy5jc3YiKSAlPiUgDQogIHNlbGVjdChNYWluX0NhdGVnLCBDb21wYW55X05hLCBDb3VudHksIEFkZHJlc3MsIFpJUF9Db2RlLCBYLCBZKSAlPiUgDQogIGZpbHRlcihDb3VudHkgPT0gIkJhbHRpbW9yZSBDaXR5IikgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JQ0KICByZW5hbWUoc3RvcmVfdHlwZSA9IDEsIG5hbWUgPSAyKSAlPiUNCiAgZmlsdGVyKHN0b3JlX3R5cGUgPT0gIlN1cGVybWFya2V0IikgJT4lIA0KICBzdF9hc19zZihjb29yZHMgPSBjKCJ4IiwgInkiKSwgY3JzID0gNDI2OSkNCiMgYmFsdGltb3JlIHNtYWxsIGdyb2Nlcnkgc3RvcmVzDQpzbWFsbF9ncm9jZXJ5IDwtIHJlYWRfY3N2KCJmb29kX3N0b3Jlcy5jc3YiKSAlPiUgDQogIHNlbGVjdChNYWluX0NhdGVnLCBDb21wYW55X05hLCBDb3VudHksIEFkZHJlc3MsIFpJUF9Db2RlLCBYLCBZKSAlPiUgDQogIGZpbHRlcihDb3VudHkgPT0gIkJhbHRpbW9yZSBDaXR5IikgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JQ0KICByZW5hbWUoc3RvcmVfdHlwZSA9IDEsIG5hbWUgPSAyKSAlPiUNCiAgZmlsdGVyKHN0b3JlX3R5cGUgPT0gIlNtYWxsIEdyb2NlcnkvQ29ybmVyIFN0b3JlIikgJT4lIA0KICBzdF9hc19zZihjb29yZHMgPSBjKCJ4IiwgInkiKSwgY3JzID0gNDI2OSkNCiMgYmFsdGltb3JlIGNvbnZlbmllbmNlIHN0b3Jlcw0KY29udmVuaWVuY2Vfc3RvcmVzIDwtIHJlYWRfY3N2KCJmb29kX3N0b3Jlcy5jc3YiKSAlPiUgDQogIHNlbGVjdChNYWluX0NhdGVnLCBDb21wYW55X05hLCBDb3VudHksIEFkZHJlc3MsIFpJUF9Db2RlLCBYLCBZKSAlPiUgDQogIGZpbHRlcihDb3VudHkgPT0gIkJhbHRpbW9yZSBDaXR5IikgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JQ0KICByZW5hbWUoc3RvcmVfdHlwZSA9IDEsIG5hbWUgPSAyKSAlPiUNCiAgZmlsdGVyKHN0b3JlX3R5cGUgPT0gIkNvbnZlbmllbmNlIFN0b3JlIikgJT4lIA0KICBzdF9hc19zZihjb29yZHMgPSBjKCJ4IiwgInkiKSwgY3JzID0gNDI2OSkNCmBgYA0KDQojY2xlYW4gbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUgZGF0YSBhbmQgbmVpZ2hib3Job29kcyBzaGFwZWZpbGUNClNlbGVjdGVkIG1vc3QgcmVjZW50IG1lZGlhbiBob3VzZWhvbGQgaW5jb21lIGRhdGEgYW5kIGNsZWFuZWQgY29sdW1uIG5hbWVzLg0KDQpUaGUgbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUgaW4gQmFsdGltb3JlIGlzICQ1MiwxNjQsIGFjY29yZGluZyB0byB0aGUgVS5TLiBDZW5zdXMgQnVyZWF1LiBUaGlzIGlzIGxlc3MgdGhhbiB0aGUgbmF0aW9uYWwgbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUgb2YgJDY1LDAwMC4gV2UgY2hvc2UgdG8gdXNlIHRoZSBCYWx0aW1vcmUgbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUgaW5zdGVhZCBvZiB0aGUgbmF0aW9uYWwgbWVkaWFuIGhvdXNlaG9sZCBpbmNvbWUgYmVjYXVzZSBpdCBpcyBtb3JlIHJlcHJlc2VudGF0aXZlIG9mIHRoZSBjaXR5LiBXZSBkZWZpbmVkIGxvdyBpbmNvbWUgYXMgYSBtZWRpYW4gaG91c2Vob2xkIGluY29tZSBiZWxvdyBCYWx0aW1vcmUncyAkNTIsMTY0IG1lZGlhbiBob3VzZWhvbGQgaW5jb21lIGFuZCBoaWdoIGluY29tZSBhcyBhYm92ZSB0aGF0IG51bWJlci4gVGhlcmUgYXJlIDMyIG5laWdoYm9yaG9vZHMgY2hhcmFjdGVyaXplZCBhcyBsb3cgaW5jb21lIGFuZCAyMyBuZWlnaGJvcmhvb2RzIGNoYXJhY3Rlcml6ZWQgYXMgaGlnaCBpbmNvbWUuDQoNCmBgYHtyfQ0KIyBMb2FkIGFuZCBjbGVhbiBsb3cgaW5jb21lIG5laWdoYm9yaG9vZCBzaGFwZWZpbGUNCmxvd19pbmNvbWUgPC0gc3RfcmVhZCgiaW5jb21lX3NoYXBlZmlsZXMvbWVkaWFuX2hvdXNlaG9sZF9pbmNvbWUuc2hwIikgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JQ0KICBzZWxlY3QoY3NhMjAxMCwgbWhoaTIwLCBnZW9tZXRyeSkgJT4lIA0KICByZW5hbWUobmVpZ2hib3Job29kID0gMSwgbWVkaWFuX2luY29tZT0yKSAlPiUNCiAgbXV0YXRlKA0KICAgIGluY29tZV9sZXZlbCA9IGNhc2Vfd2hlbigNCiAgICAgICAgbWVkaWFuX2luY29tZSA8IDUyMTY0IH4gImxvdyIsDQogICAgICAgIG1lZGlhbl9pbmNvbWUgPj0gNTIxNjQgfiAiaGlnaCINCiAgICAgICkNCiAgKSAlPiUgDQogIGZpbHRlcihpbmNvbWVfbGV2ZWwgPT0gImxvdyIpICU+JQ0KICBzdF90cmFuc2Zvcm0oY3JzPTQyNjkpDQojIExvYWQgYW5kIGNsZWFuIGhpZ2ggaW5jb21lIG5laWdoYm9yaG9vZCBzaGFwZWZpbGUNCmhpZ2hfaW5jb21lIDwtIHN0X3JlYWQoImluY29tZV9zaGFwZWZpbGVzL21lZGlhbl9ob3VzZWhvbGRfaW5jb21lLnNocCIpICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUNCiAgc2VsZWN0KGNzYTIwMTAsIG1oaGkyMCwgZ2VvbWV0cnkpICU+JSANCiAgcmVuYW1lKG5laWdoYm9yaG9vZCA9IDEsIG1lZGlhbl9pbmNvbWU9MikgJT4lDQogIG11dGF0ZSgNCiAgICBpbmNvbWVfbGV2ZWwgPSBjYXNlX3doZW4oDQogICAgICAgIG1lZGlhbl9pbmNvbWUgPCA1MjE2NCB+ICJsb3ciLA0KICAgICAgICBtZWRpYW5faW5jb21lID49IDUyMTY0IH4gImhpZ2giDQogICAgICApDQogICkgJT4lIA0KICBmaWx0ZXIoaW5jb21lX2xldmVsID09ICJoaWdoIikgJT4lDQogIHN0X3RyYW5zZm9ybShjcnM9NDI2OSkNCmBgYA0KDQojSG93IGRvZXMgdGhlIG51bWJlciBvZiBzdXBlcm1hcmtldHMgY29tcGFyZSBpbiBsb3cgaW5jb21lIGFuZCBoaWdoIGluY29tZSBCYWx0aW1vcmUgbmVpZ2hib3Job29kcz8NClRoZXJlIGFyZSAyNSBzdXBlcm1hcmtldHMgaW4gbG93IGluY29tZSBuZWlnaGJvcmhvb2RzIGFuZCAyNCBzdXBlcm1hcmtldHMgaW4gaGlnaCBpbmNvbWUgbmVpZ2hib3Job29kcy4gV2hpbGUgbG93IGluY29tZSBuZWlnaGJvcmhvb2RzIGhhdmUgb25lIG1vcmUgc3VwZXJtYXJrZXQgdGhhbiBoaWdoIGluY29tZSBuZWlnaGJvcmhvb2RzLCB0aGVyZSBhcmUgbW9yZSBsb3cgaW5jb21lIG5laWdoYm9yaG9vZHMgKDMyKSB0aGFuIGhpZ2ggaW5jb21lIG5laWdoYm9yaG9vZHMgKDIzKSwgbWFraW5nIHRoZSByYXRpbyBvZiBzdXBlcm1hcmtldHMgdG8gbmVpZ2hib3Job29kcyBncmVhdGVyIGZvciBoaWdoIGluY29tZSBuZWlnaGJvcmhvb2RzLiBUaGVyZSBhcmUgbW9yZSB0aGFuIHNldmVuIGxvdyBpbmNvbWUgbmVpZ2hib3Job29kcyB3aXRob3V0IGEgc3VwZXJtYXJrZXQuIEV2ZXJ5IGhpZ2ggaW5jb21lIG5laWdoYm9yaG9vZCBoYXMgYSBzdXBlcm1hcmtldCwgcGx1cyBhbiBhZGRpdGlvbmFsIG9uZS4gVGhpcyBzaG93cyB0aGF0IGhpZ2ggaW5jb21lIHJlc2lkZW50cyBoYXZlIGdyZWF0ZXIgYWNjZXNzIHRvIHN1cGVybWFya2V0cyBhbmQgZnJlc2ggZm9vZCB0aGFuIGxvdyBpbmNvbWUgcmVzaWRlbnRzLg0KDQpgYGB7cn0NCiMgc29ydCBjb29yZGluYXRlcyBpbnRvIGxvdyBpbmNvbWUgbmVpZ2hib3Job29kcw0KbG93X2luY29tZV9zdXBlcm1hcmtldHMgPC0gc3VwZXJtYXJrZXRzICU+JQ0KICBzdF9qb2luKGxvd19pbmNvbWUpICU+JSANCiAgZmlsdGVyKGluY29tZV9sZXZlbCA9PSAibG93IikNCiMgc29ydCBjb29yZGluYXRlcyBpbnRvIGhpZ2ggaW5jb21lIG5laWdoYm9yaG9vZHMNCmhpZ2hfaW5jb21lX3N1cGVybWFya2V0cyA8LSBzdXBlcm1hcmtldHMgJT4lDQogIHN0X2pvaW4oaGlnaF9pbmNvbWUpICU+JSANCiAgZmlsdGVyKGluY29tZV9sZXZlbCA9PSAiaGlnaCIpDQpgYGANCg0KI3Bsb3Qgc3VwZXJtYXJrZXRzIGluIGJhbHRpbW9yZSBiYXNlZCBvbiBpbmNvbWUNCmBgYHtyfQ0KZ2dwbG90KCkrDQpnZW9tX3NmKGRhdGE9bmVpZ2hib3Job29kcykrDQpnZW9tX3NmKGRhdGE9bG93X2luY29tZV9zdXBlcm1hcmtldHMgJT4lIHN0X2FzX3NmKGNvb3JkcyA9IGMoIngiLCAieSIpLCBjcnMgPSA0MzI2KSwgbWFwcGluZz1hZXMoY29sb3I9aW5jb21lX2xldmVsKSkrDQpnZW9tX3NmKGRhdGE9aGlnaF9pbmNvbWVfc3VwZXJtYXJrZXRzICU+JSBzdF9hc19zZihjb29yZHMgPSBjKCJ4IiwgInkiKSwgY3JzID0gNDMyNiksIG1hcHBpbmc9YWVzKGNvbG9yPWluY29tZV9sZXZlbCkpKw0KdGhlbWVfbWluaW1hbCgpKw0KbGFicyh0aXRsZSA9ICJTdXBlcm1hcmtldHMgaW4gSGlnaCBhbmQgTG93IEluY29tZSBCYWx0aW1vcmUgTmVpZ2hib3Job29kcyIsIA0KICAgICAgIHN1YnRpdGxlID0gIkpvaG5zIEhvcGtpbnMgYW5kIEJhbHRpbW9yZSBOZWlnaGJvcmhvb2QgSW5kaWNhdG9ycyBBbGxpYW5jZSBEYXRhLCAyMDIyIiwNCiAgICAgICBjYXB0aW9uID0gIkdyYXBoaWMgYnkgTmF0YWxpZSBBZGFtcyIpDQpgYGANCg0KI0hvdyBkb2VzIHRoZSBudW1iZXIgb2Ygc21hbGwgZ3JvY2VyeSBhbmQgY29ybmVyIHN0b3JlcyBjb21wYXJlIGluIGxvdyBpbmNvbWUgYW5kIGhpZ2ggaW5jb21lIEJhbHRpbW9yZSBuZWlnaGJvcmhvb2RzPw0KVGhlcmUgYXJlIDI4OSBzbWFsbCBncm9jZXJ5L2Nvcm5lciBzdG9yZXMgaW4gbG93IGluY29tZSBuZWlnaGJvcmhvb2RzIGFuZCAxMTUgc21hbGwgZ3JvY2VyeS9jb3JuZXIgc3RvcmVzIGluIGhpZ2ggaW5jb21lIG5laWdoYm9yaG9vZHMuIExvdyBpbmNvbWUgbmVpZ2hib3Job29kcyBoYXZlIG1vcmUgdGhhbiB0d2ljZSBhcyBtYW55IHNtYWxsIGdyb2NlcnkvY29ybmVyIHN0b3JlcyB0aGFuIGhpZ2ggaW5jb21lIG5laWdoYm9yaG9vZHMgYW5kIGhhdmUgYSBncmVhdGVyIHJhdGlvIG9mIHNtYWxsIGdyb2NlcnkvY29ybmVyIHN0b3JlcyB0aGFuIGhpZ2ggaW5jb21lIG5laWdoYm9yaG9vZHMuIFNtYWxsIGdyb2NlcnkvY29ybmVyIHN0b3JlcyB0eXBpY2FsbHkgb2ZmZXIgZXRobmljIG9yIGN1bHR1cmFsIGZvb2Qgb3B0aW9ucywgc3VjaCBhcyBBc2lhbiBvciBTb3V0aCBBbWVyaWNhbi4gVGhlIHByZXZhbGVuY2Ugb2Ygc21hbGwgZ3JvY2VyeS9jb3JuZXIgc3RvcmVzIGluIGxvdyBpbmNvbWUgbmVpZ2hib3Job29kcyBpbmRpY2F0ZXMgYSBwb3NzaWJsZSBoaWdoIG5vbi13aGl0ZSBwb3B1bGF0aW9uIGluIHRob3NlIG5laWdoYm9yaG9vZHMuIFNtYWxsIGdyb2NlcnkvY29ybmVyIHN0b3JlcyBjb3VsZCBhbHNvIG1ha2UgdXAgZm9yIHRoZSBhYnNlbmNlIG9mIGFjY2VzcyB0byBzdXBlcm1hcmtldHMgaW4gdGhlc2UgY29tbXVuaXRpZXMsIGFsdGhvdWdoIGFjY2VzcyB0byBmcmVzaCBmb29kIGNvdWxkIHN0aWxsIGJlIGxpbWl0ZWQuDQoNCmBgYHtyfQ0KIyBzb3J0IGNvb3JkaW5hdGVzIGludG8gbG93IGluY29tZSBuZWlnaGJvcmhvb2RzDQpsb3dfaW5jb21lX3NtYWxsX2dyb2NlcnkgPC0gc21hbGxfZ3JvY2VyeSAlPiUNCiAgc3Rfam9pbihsb3dfaW5jb21lKSAlPiUgDQogIGZpbHRlcihpbmNvbWVfbGV2ZWwgPT0gImxvdyIpDQojIHNvcnQgY29vcmRpbmF0ZXMgaW50byBoaWdoIGluY29tZSBuZWlnaGJvcmhvb2RzDQpoaWdoX2luY29tZV9zbWFsbF9ncm9jZXJ5IDwtIHNtYWxsX2dyb2NlcnkgJT4lDQogIHN0X2pvaW4oaGlnaF9pbmNvbWUpICU+JSANCiAgZmlsdGVyKGluY29tZV9sZXZlbCA9PSAiaGlnaCIpDQpgYGANCg0KI3Bsb3Qgc21hbGwgZ3JvY2VyeSBzdG9yZXMgaW4gYmFsdGltb3JlIGJhc2VkIG9uIGluY29tZQ0KYGBge3J9DQpnZ3Bsb3QoKSsNCmdlb21fc2YoZGF0YT1uZWlnaGJvcmhvb2RzKSsNCmdlb21fc2YoZGF0YT1sb3dfaW5jb21lX3NtYWxsX2dyb2NlcnkgJT4lIHN0X2FzX3NmKGNvb3JkcyA9IGMoIngiLCAieSIpLCBjcnMgPSA0MzI2KSwgbWFwcGluZz1hZXMoY29sb3I9aW5jb21lX2xldmVsKSkrDQpnZW9tX3NmKGRhdGE9aGlnaF9pbmNvbWVfc21hbGxfZ3JvY2VyeSAlPiUgc3RfYXNfc2YoY29vcmRzID0gYygieCIsICJ5IiksIGNycyA9IDQzMjYpLCBtYXBwaW5nPWFlcyhjb2xvcj1pbmNvbWVfbGV2ZWwpKSsNCnRoZW1lX21pbmltYWwoKSsNCmxhYnModGl0bGUgPSAiU21hbGwgR3JvY2VyeSBhbmQgQ29ybmVyIFN0b3JlcyBpbiBIaWdoIGFuZCBMb3cgSW5jb21lIEJhbHRpbW9yZSBOZWlnaGJvcmhvb2RzIiwgDQogICAgICAgc3VidGl0bGUgPSAiSm9obnMgSG9wa2lucyBhbmQgQmFsdGltb3JlIE5laWdoYm9yaG9vZCBJbmRpY2F0b3JzIEFsbGlhbmNlIERhdGEsIDIwMjIiLA0KICAgICAgIGNhcHRpb24gPSAiR3JhcGhpYyBieSBOYXRhbGllIEFkYW1zIikNCmBgYA0KDQojSG93IGRvZXMgdGhlIG51bWJlciBvZiBjb252ZW5pZW5jZSBzdG9yZXMgY29tcGFyZSBpbiBsb3cgaW5jb21lIGFuZCBoaWdoIGluY29tZSBCYWx0aW1vcmUgbmVpZ2hib3Job29kcz8NClRoZXJlIGFyZSAxNjYgY29udmVuaWVuY2Ugc3RvcmVzIGluIGxvdyBpbmNvbWUgbmVpZ2hib3Job29kcyBhbmQgMTE2IGNvbnZlbmllbmNlIHN0b3JlcyBpbiBoaWdoIGluY29tZSBuZWlnaGJvcmhvb2RzLiBUaGUgYXZlcmFnZSBudW1iZXIgb2YgY29udmVuaWVuY2Ugc3RvcmVzIGluIGxvdyBhbmQgaGlnaCBpbmNvbWUgbmVpZ2hib3Job29kcyBpcyB2aXJ0dWFsbHkgdGhlIHNhbWUgKDUuMSBpbiBsb3cgaW5jb21lIGNvbXBhcmVkIHRvIDUuMCBpbiBoaWdoIGluY29tZSkuICBDb252ZW5pZW5jZSBzdG9yZXMgdHlwaWNhbGx5IGhhdmUgImp1bmsgZm9vZCIgYW5kIHNuYWNrcywgbGlrZSBjaGlwcywgc29kYSBhbmQgY2FuZHkuIExhcmdlIGNoYWluIGNvbnZlbmllbmNlIHN0b3Jlcywgc3VjaCBhcyBSb3lhbCBGYXJtcyBhbmQgV2F3YSwgaGF2ZSBvcHRpb25zIHRvIG9yZGVyIGhvdCBmb29kLCBsaWtlIGZyaWVkIGNoaWNrZW4gYW5kIHNhbmR3aWNoZXMuIFNvbWUgY29udmVuaWVuY2Ugc3RvcmVzIGhhdmUgZnJlc2ggZnJ1aXQsIHN1Y2ggYXMgYXBwbGVzIGFuZCBiYW5hbmFzLCBidXQgb3ZlcmFsbCwgZG8gbm90IG9mZmVyIGdyZWF0IGFjY2VzcyB0byBmcmVzaCBmb29kLiBXaGlsZSB0aGVyZSBpcyBhbiBlcXVhbCBwZXJjZW50YWdlIG9mIGNvbnZlbmllbmNlIHN0b3JlcyBpbiBoaWdoIGluY29tZSBhbmQgbG93IGluY29tZSBuZWlnaGJvcmhvb2RzLCB0aGUgbG93ZXIgcGVyY2VudGFnZSBvZiBzdXBlcm1hcmtldHMgaW4gbG93IGluY29tZSBuZWlnaGJvcmhvb2RzIGNvdWxkIGluZGljYXRlIGEgc3Ryb25nZXIgcmVsaWFuY2Ugb24gY29udmVuaWVuY2Ugc3RvcmVzIGZvciBidXlpbmcgZm9vZC4NCg0KYGBge3J9DQojIHNvcnQgY29vcmRpbmF0ZXMgaW50byBsb3cgaW5jb21lIG5laWdoYm9yaG9vZHMNCmxvd19pbmNvbWVfY29udmVuaWVuY2Vfc3RvcmVzIDwtIGNvbnZlbmllbmNlX3N0b3JlcyAlPiUNCiAgc3Rfam9pbihsb3dfaW5jb21lKSAlPiUgDQogIGZpbHRlcihpbmNvbWVfbGV2ZWwgPT0gImxvdyIpDQojIHNvcnQgY29vcmRpbmF0ZXMgaW50byBoaWdoIGluY29tZSBuZWlnaGJvcmhvb2RzDQpoaWdoX2luY29tZV9jb252ZW5pZW5jZV9zdG9yZXMgPC0gY29udmVuaWVuY2Vfc3RvcmVzICU+JQ0KICBzdF9qb2luKGhpZ2hfaW5jb21lKSAlPiUgDQogIGZpbHRlcihpbmNvbWVfbGV2ZWwgPT0gImhpZ2giKQ0KYGBgDQoNCiNwbG90IGNvbnZlbmllbmNlIHN0b3JlcyBpbiBiYWx0aW1vcmUgYmFzZWQgb24gaW5jb21lDQpgYGB7cn0NCmdncGxvdCgpKw0KZ2VvbV9zZihkYXRhPW5laWdoYm9yaG9vZHMpKw0KZ2VvbV9zZihkYXRhPWxvd19pbmNvbWVfY29udmVuaWVuY2Vfc3RvcmVzICU+JSBzdF9hc19zZihjb29yZHMgPSBjKCJ4IiwgInkiKSwgY3JzID0gNDMyNiksIG1hcHBpbmc9YWVzKGNvbG9yPWluY29tZV9sZXZlbCkpKw0KZ2VvbV9zZihkYXRhPWhpZ2hfaW5jb21lX2NvbnZlbmllbmNlX3N0b3JlcyAlPiUgc3RfYXNfc2YoY29vcmRzID0gYygieCIsICJ5IiksIGNycyA9IDQzMjYpLCBtYXBwaW5nPWFlcyhjb2xvcj1pbmNvbWVfbGV2ZWwpKSsNCnRoZW1lX21pbmltYWwoKSsNCmxhYnModGl0bGUgPSAiQ29udmVuaWVuY2UgU3RvcmVzIGluIEhpZ2ggYW5kIExvdyBJbmNvbWUgQmFsdGltb3JlIE5laWdoYm9yaG9vZHMiLCANCiAgICAgICBzdWJ0aXRsZSA9ICJKb2hucyBIb3BraW5zIGFuZCBCYWx0aW1vcmUgTmVpZ2hib3Job29kIEluZGljYXRvcnMgQWxsaWFuY2UgRGF0YSwgMjAyMiIsDQogICAgICAgY2FwdGlvbiA9ICJHcmFwaGljIGJ5IE5hdGFsaWUgQWRhbXMiKQ0KYGBgDQoNCiNjbGVhbiByYWNlIGRhdGEgYW5kIG5laWdoYm9yaG9vZHMgc2hhcGVmaWxlDQpTZWxlY3RlZCB3aGl0ZSBkYXRhIGFuZCBjbGVhbmVkIGNvbHVtbiBuYW1lcy4NCg0KV2UgZGVmaW5lZCBtYWpvcml0eSB3aGl0ZSBuZWlnaGJvcmhvb2RzIGFzIG5laWdoYm9yaG9vZHMgd2l0aCBhIG5laWdoYm9yaG9vZCB3aXRoIGEgNTAlIG9yIGdyYXRlciB3aGl0ZSBwb3B1bGF0aW9uIGFuZCBub24gbWFqb3JpdHkgd2hpdGUgbmVpZ2hib3Job29kcyBhcyBhIG5laWdoYm9yaG9vZCB3aXRoIGEgbGVzcyB0aGFuIDUwJSB3aGl0ZSBwb3B1bGF0aW9uLiBUaGVyZSBhcmUgMTEgbWFqb3JpdHkgd2hpdGUgbmVpZ2hib3Job29kcyBhbmQgNDQgbm9uIG1ham9yaXR5IHdoaXRlIG5laWdoYm9yaG9vZHMuDQoNCmBgYHtyfQ0KIyBmaWx0ZXIgZm9yIG1ham9yaXR5IHdoaXRlIG5laWdoYm9yaG9vZHMNCm1ham9yaXR5X3doaXRlIDwtIHN0X3JlYWQoImluY29tZV9zaGFwZWZpbGVzL21lZGlhbl9ob3VzZWhvbGRfaW5jb21lLnNocCIpICU+JSANCiAgY2xlYW5fbmFtZXMoKSAlPiUNCiAgc2VsZWN0KGNzYTIwMTAsIGdlb21ldHJ5KSAlPiUgDQogIHJlbmFtZShuZWlnaGJvcmhvb2QgPSAxKSAlPiUgDQogIGlubmVyX2pvaW4ocGVyY2VudF93aGl0ZTIsIGJ5PSJuZWlnaGJvcmhvb2QiKSAlPiUgDQogIG11dGF0ZSgNCiAgICBwb3B1bGF0aW9uX3N0YXR1cyA9IGNhc2Vfd2hlbigNCiAgICAgICAgcGVyY2VudF93aGl0ZSA8IDUwIH4gIm5vbl9tYWpvcml0eV93aGl0ZSIsDQogICAgICAgIHBlcmNlbnRfd2hpdGUgPj0gNTAgfiAibWFqb3JpdHlfd2hpdGUiDQogICAgICApDQogICkgJT4lDQogIGZpbHRlcihwb3B1bGF0aW9uX3N0YXR1cyA9PSAibWFqb3JpdHlfd2hpdGUiKSAlPiUNCiAgc3RfdHJhbnNmb3JtKGNycz00MjY5KQ0KIyBmaWx0ZXIgZm9yIG5vbiBtYWpvcml0eSB3aGl0ZSBuZWlnaGJvcmhvb2RzDQpub25fbWFqb3JpdHlfd2hpdGUgPC0gc3RfcmVhZCgiaW5jb21lX3NoYXBlZmlsZXMvbWVkaWFuX2hvdXNlaG9sZF9pbmNvbWUuc2hwIikgJT4lIA0KICBjbGVhbl9uYW1lcygpICU+JQ0KICBzZWxlY3QoY3NhMjAxMCwgZ2VvbWV0cnkpICU+JSANCiAgcmVuYW1lKG5laWdoYm9yaG9vZCA9IDEpICU+JSANCiAgaW5uZXJfam9pbihwZXJjZW50X3doaXRlMiwgYnk9Im5laWdoYm9yaG9vZCIpICU+JSANCiAgbXV0YXRlKA0KICAgIHBvcHVsYXRpb25fc3RhdHVzID0gY2FzZV93aGVuKA0KICAgICAgICBwZXJjZW50X3doaXRlIDwgNTAgfiAibm9uX21ham9yaXR5X3doaXRlIiwNCiAgICAgICAgcGVyY2VudF93aGl0ZSA+PSA1MCB+ICJtYWpvcml0eV93aGl0ZSINCiAgICAgICkNCiAgKSAlPiUNCiAgZmlsdGVyKHBvcHVsYXRpb25fc3RhdHVzID09ICJub25fbWFqb3JpdHlfd2hpdGUiKSAlPiUNCiAgc3RfdHJhbnNmb3JtKGNycz00MjY5KQ0KYGBgDQoNCiNIb3cgZG9lcyB0aGUgbnVtYmVyIG9mIHN1cGVybWFya2V0cyBjb21wYXJlIGluIG1ham9yaXR5IHdoaXRlIGFuZCBub24gbWFqb3JpdHkgd2hpdGUgQmFsdGltb3JlIG5laWdoYm9yaG9vZHM/DQpUaGVyZSBhcmUgMTQgc3VwZXJtYXJrZXRzIGluIG1ham9yaXR5IHdoaXRlIG5laWdoYm9yaG9vZHMgYW5kIDM1IHN1cGVybWFya2V0cyBpbiBub24gbWFqb3JpdHkgd2hpdGUgbmVpZ2hib3Job29kcy4gV2hpbGUgbm9uIG1ham9yaXR5IHdoaXRlIG5laWdoYm9yaG9vZHMgaGF2ZSBhIGhpZ2hlciBudW1iZXIgb2Ygc3VwZXJtYXJrZXRzIHRoZSByYXRpbyBvZiBzdXBlcm1hcmtldHMgZm9yIG1ham9yaXR5IHdoaXRlIG5laWdoYm9yaG9vZHMgKDE0IHN1cGVybWFya2V0cyBmb3IgMTEgbmVpZ2hib3Job29kcykgaXMgZ3JlYXRlciB0aGFuIHRoZSByYXRpbyBvZiBzdXBlcm1hcmtldHMgZm9yIG5vbiBtYWpvcml0eSB3aGl0ZSBuZWlnaGJvcmhvb2RzICgzNSBzdXBlcm1hcmtldHMgZm9yIDQ0IG5laWdoYm9yaG9vZHMpLiBUaGlzIGluZGljYXRlcyB0aGF0IHdoaXRlIHJlc2lkZW50cyBoYXZlIGdyZWF0ZXIgYWNjZXNzIHRvIHN1cGVybWFya2V0cyBhbmQgZnJlc2ggZm9vZCB0aGFuIG5vbiB3aGl0ZSByZXNpZGVudHMuDQoNCmBgYHtyfQ0KIyBzb3J0IGNvb3JkaW5hdGVzIGludG8gbWFqb3JpdHkgd2hpdGUgbmVpZ2hib3Job29kcw0KbWFqb3JpdHlfd2hpdGVfc3VwZXJtYXJrZXRzIDwtIHN1cGVybWFya2V0cyAlPiUNCiAgc3Rfam9pbihtYWpvcml0eV93aGl0ZSkgJT4lIA0KICBmaWx0ZXIocG9wdWxhdGlvbl9zdGF0dXMgPT0gIm1ham9yaXR5X3doaXRlIikNCiMgc29ydCBjb29yZGluYXRlcyBpbnRvIG5vbiBtYWpvcml0eSB3aGl0ZSBuZWlnaGJvcmhvb2RzDQpub25fbWFqb3JpdHlfd2hpdGVfc3VwZXJtYXJrZXRzIDwtIHN1cGVybWFya2V0cyAlPiUNCiAgc3Rfam9pbihub25fbWFqb3JpdHlfd2hpdGUpICU+JSANCiAgZmlsdGVyKHBvcHVsYXRpb25fc3RhdHVzID09ICJub25fbWFqb3JpdHlfd2hpdGUiKQ0KYGBgDQoNCiNwbG90IHN1cGVybWFya2V0cyBpbiBiYWx0aW1vcmUgYmFzZWQgb24gcmFjZQ0KYGBge3J9DQpnZ3Bsb3QoKSsNCmdlb21fc2YoZGF0YT1uZWlnaGJvcmhvb2RzKSsNCmdlb21fc2YoZGF0YT1tYWpvcml0eV93aGl0ZV9zdXBlcm1hcmtldHMgJT4lIHN0X2FzX3NmKGNvb3JkcyA9IGMoIngiLCAieSIpLCBjcnMgPSA0MzI2KSwgbWFwcGluZz1hZXMoY29sb3I9cG9wdWxhdGlvbl9zdGF0dXMpKSsNCmdlb21fc2YoZGF0YT1ub25fbWFqb3JpdHlfd2hpdGVfc3VwZXJtYXJrZXRzICU+JSBzdF9hc19zZihjb29yZHMgPSBjKCJ4IiwgInkiKSwgY3JzID0gNDMyNiksIG1hcHBpbmc9YWVzKGNvbG9yPXBvcHVsYXRpb25fc3RhdHVzKSkrDQp0aGVtZV9taW5pbWFsKCkrDQpsYWJzKHRpdGxlID0gIlN1cGVybWFya2V0cyBpbiBNYWpvcml0eSBXaGl0ZSBhbmQgTm9uIE1ham9yaXR5IFdoaXRlIEJhbHRpbW9yZSBOZWlnaGJvcmhvb2RzIiwgDQogICAgICAgc3VidGl0bGUgPSAiSm9obnMgSG9wa2lucyBhbmQgQmFsdGltb3JlIE5laWdoYm9yaG9vZCBJbmRpY2F0b3JzIEFsbGlhbmNlIERhdGEsIDIwMjIiLA0KICAgICAgIGNhcHRpb24gPSAiR3JhcGhpYyBieSBOYXRhbGllIEFkYW1zIikNCmBgYA0KDQojSG93IGRvZXMgdGhlIG51bWJlciBvZiBzbWFsbCBncm9jZXJ5IGFuZCBjb3JuZXIgc3RvcmVzIGNvbXBhcmUgaW4gbWFqb3JpdHkgd2hpdGUgYW5kIG5vbiBtYWpvcml0eSB3aGl0ZSBCYWx0aW1vcmUgbmVpZ2hib3Job29kcz8NClRoZXJlIGFyZSAxMiB0aW1lcyBhcyBtYW55IHNtYWxsIGdyb2NlcnkvY29ybmVyIHN0b3JlcyBpbiBub24gbWFqb3JpdHkgd2hpdGUgbmVpZ2hib3Job29kcyAoMzczKSB0aGFuIG1ham9yaXR5IHdoaXRlIG5laWdoYm9yaG9vZHMgKDMxKS4gU21hbGwgZ3JvY2VyeS9jb3JuZXIgc3RvcmVzIHR5cGljYWxseSBvZmZlciBldGhuaWMgb3IgY3VsdHVyYWwgZm9vZCBvcHRpb25zLCBzdWNoIGFzIEFzaWFuIG9yIFNvdXRoIEFtZXJpY2FuLCBzbyBpdCBtYWtlcyBzZW5zZSBmb3IgbW9zdCBvZiB0aGVzZSBzdG9yZXMgdG8gYmUgaW4gbWFqb3JpdHkgbm9uIHdoaXRlIGNvbW11bml0aWVzLiBJdCBpcyB1bmNsZWFyIGZyb20gdGhpcyBkYXRhIHdoZXRoZXIgdGhlIGhpZ2ggbnVtYmVyIG9mIHNtYWxsIGdyb2NlcnkvY29ybmVyIHN0b3JlcyBpcyBkdWUgdG8gcHJlZmVyZW5jZSBvZiB0aGUgbmVpZ2hib3Job29kIHBvcHVsYXRpb25zLCBhIGxhY2sgb2YgYWNjZXNzIHRvIG90aGVyIHR5cGVzIG9mIGZvb2Qgc3RvcmVzIChzdWNoIGFzIHN1cGVybWFya2V0cyksIG90aGVyIGZhY3RvcnMgb3IgYSBjb21iaW5hdGlvbiBvZiBmYWN0b3JzLg0KDQpgYGB7cn0NCiMgc29ydCBjb29yZGluYXRlcyBpbnRvIG1ham9yaXR5IHdoaXRlIG5laWdoYm9yaG9vZHMNCm1ham9yaXR5X3doaXRlX3NtYWxsX2dyb2NlcnkgPC0gc21hbGxfZ3JvY2VyeSAlPiUNCiAgc3Rfam9pbihtYWpvcml0eV93aGl0ZSkgJT4lIA0KICBmaWx0ZXIocG9wdWxhdGlvbl9zdGF0dXMgPT0gIm1ham9yaXR5X3doaXRlIikNCiMgc29ydCBjb29yZGluYXRlcyBpbnRvIG5vbiBtYWpvcml0eSB3aGl0ZSBuZWlnaGJvcmhvb2RzDQpub25fbWFqb3JpdHlfd2hpdGVfc21hbGxfZ3JvY2VyeSA8LSBzbWFsbF9ncm9jZXJ5ICU+JQ0KICBzdF9qb2luKG5vbl9tYWpvcml0eV93aGl0ZSkgJT4lIA0KICBmaWx0ZXIocG9wdWxhdGlvbl9zdGF0dXMgPT0gIm5vbl9tYWpvcml0eV93aGl0ZSIpDQpgYGANCg0KI3Bsb3Qgc21hbGwgZ3JvY2VyeSBzdG9yZXMgaW4gYmFsdGltb3JlIGJhc2VkIG9uIHJhY2UNCmBgYHtyfQ0KZ2dwbG90KCkrDQpnZW9tX3NmKGRhdGE9bmVpZ2hib3Job29kcykrDQpnZW9tX3NmKGRhdGE9bWFqb3JpdHlfd2hpdGVfc21hbGxfZ3JvY2VyeSAlPiUgc3RfYXNfc2YoY29vcmRzID0gYygieCIsICJ5IiksIGNycyA9IDQzMjYpLCBtYXBwaW5nPWFlcyhjb2xvcj1wb3B1bGF0aW9uX3N0YXR1cykpKw0KZ2VvbV9zZihkYXRhPW5vbl9tYWpvcml0eV93aGl0ZV9zbWFsbF9ncm9jZXJ5ICU+JSBzdF9hc19zZihjb29yZHMgPSBjKCJ4IiwgInkiKSwgY3JzID0gNDMyNiksIG1hcHBpbmc9YWVzKGNvbG9yPXBvcHVsYXRpb25fc3RhdHVzKSkrDQp0aGVtZV9taW5pbWFsKCkrDQpsYWJzKHRpdGxlID0gIlNtYWxsIEdyb2NlcnkgYW5kIENvcm5lciBTdG9yZXMgaW4gTWFqb3JpdHkgV2hpdGUgYW5kIE5vbiBNYWpvcml0eSBXaGl0ZSBCYWx0aW1vcmUgTmVpZ2hib3Job29kcyIsIA0KICAgICAgIHN1YnRpdGxlID0gIkpvaG5zIEhvcGtpbnMgYW5kIEJhbHRpbW9yZSBOZWlnaGJvcmhvb2QgSW5kaWNhdG9ycyBBbGxpYW5jZSBEYXRhLCAyMDIyIiwNCiAgICAgICBjYXB0aW9uID0gIkdyYXBoaWMgYnkgTmF0YWxpZSBBZGFtcyIpDQpgYGANCg0KI0hvdyBkb2VzIHRoZSBudW1iZXIgb2YgY29udmVuaWVuY2Ugc3RvcmVzIGNvbXBhcmUgaW4gbWFqb3JpdHkgd2hpdGUgYW5kIG5vbiBtYWpvcml0eSB3aGl0ZSBCYWx0aW1vcmUgbmVpZ2hib3Job29kcz8NClRoZXJlIGFyZSA0OSBjb252ZW5pZW5jZSBzdG9yZXMgaW4gbWFqb3JpdHkgd2hpdGUgbmVpZ2hib3Job29kcyBhbmQgMjMzIGNvbnZlbmllbmNlIHN0b3JlcyBpbiBub24gbWFqb3JpdHkgd2hpdGUgbmVpZ2hib3Job29kcy4gVGhlIHBlcmNlbnRhZ2Ugb2YgY29udmVuaWVuY2Ugc3RvcmVzIGluIG1ham9yaXR5IHdoaXRlIGFuZCBub24gbWFqb3JpdHkgd2hpdGUgbmVpZ2hib3Job29kcyBpcyBuZWFybHkgZXF1YWwgKDQuNSBpbiBtYWpvcml0eSB3aGl0ZSBjb21wYXJlZCB0byA1LjMgaW4gbm9uIG1ham9yaXR5IHdoaXRlKS4gQ29udmVuaWVuY2Ugc3RvcmVzIHR5cGljYWxseSBoYXZlICJqdW5rIGZvb2QiIGFuZCBzbmFja3MsIGxpa2UgY2hpcHMsIHNvZGEgYW5kIGNhbmR5LiBMYXJnZSBjaGFpbiBjb252ZW5pZW5jZSBzdG9yZXMsIHN1Y2ggYXMgUm95YWwgRmFybXMgYW5kIFdhd2EsIGhhdmUgb3B0aW9ucyB0byBvcmRlciBob3QgZm9vZCwgbGlrZSBmcmllZCBjaGlja2VuIGFuZCBzYW5kd2ljaGVzLiBTb21lIGNvbnZlbmllbmNlIHN0b3JlcyBoYXZlIGZyZXNoIGZydWl0LCBzdWNoIGFzIGFwcGxlcyBhbmQgYmFuYW5hcywgYnV0IG92ZXJhbGwsIGRvIG5vdCBvZmZlciBncmVhdCBhY2Nlc3MgdG8gZnJlc2ggZm9vZC4gV2hpbGUgdGhlcmUgaXMgYSBuZWFybHkgZXF1YWwgcGVyY2VudGFnZSBvZiBjb252ZW5pZW5jZSBzdG9yZXMgaW4gbWFqb3JpdHkgd2hpdGUgYW5kIG5vbiBtYWpvcml0eSB3aGl0ZSBuZWlnaGJvcmhvb2RzLCB0aGUgbG93ZXIgcGVyY2VudGFnZSBvZiBzdXBlcm1hcmtldHMgaW4gbm9uIG1ham9yaXR5IHdoaXRlIG5laWdoYm9yaG9vZHMgY291bGQgaW5kaWNhdGUgYSBzdHJvbmdlciByZWxpYW5jZSBvbiBjb252ZW5pZW5jZSBzdG9yZXMgZm9yIGJ1eWluZyBmb29kLg0KDQpgYGB7cn0NCiMgc29ydCBjb29yZGluYXRlcyBpbnRvIG1ham9yaXR5IHdoaXRlIG5laWdoYm9yaG9vZHMNCm1ham9yaXR5X3doaXRlX2NvbnZlbmllbmNlX3N0b3JlcyA8LSBjb252ZW5pZW5jZV9zdG9yZXMgJT4lDQogIHN0X2pvaW4obWFqb3JpdHlfd2hpdGUpICU+JSANCiAgZmlsdGVyKHBvcHVsYXRpb25fc3RhdHVzID09ICJtYWpvcml0eV93aGl0ZSIpDQojIHNvcnQgY29vcmRpbmF0ZXMgaW50byBub24gbWFqb3JpdHkgd2hpdGUgbmVpZ2hib3Job29kcw0Kbm9uX21ham9yaXR5X3doaXRlX2NvbnZlbmllbmNlX3N0b3JlcyA8LSBjb252ZW5pZW5jZV9zdG9yZXMgJT4lDQogIHN0X2pvaW4obm9uX21ham9yaXR5X3doaXRlKSAlPiUgDQogIGZpbHRlcihwb3B1bGF0aW9uX3N0YXR1cyA9PSAibm9uX21ham9yaXR5X3doaXRlIikNCmBgYA0KDQojcGxvdCBjb252ZW5pZW5jZSBzdG9yZXMgaW4gYmFsdGltb3JlIGJhc2VkIG9uIHJhY2UNCmBgYHtyfQ0KZ2dwbG90KCkrDQpnZW9tX3NmKGRhdGE9bmVpZ2hib3Job29kcykrDQpnZW9tX3NmKGRhdGE9bWFqb3JpdHlfd2hpdGVfY29udmVuaWVuY2Vfc3RvcmVzICU+JSBzdF9hc19zZihjb29yZHMgPSBjKCJ4IiwgInkiKSwgY3JzID0gNDMyNiksIG1hcHBpbmc9YWVzKGNvbG9yPXBvcHVsYXRpb25fc3RhdHVzKSkrDQpnZW9tX3NmKGRhdGE9bm9uX21ham9yaXR5X3doaXRlX2NvbnZlbmllbmNlX3N0b3JlcyAlPiUgc3RfYXNfc2YoY29vcmRzID0gYygieCIsICJ5IiksIGNycyA9IDQzMjYpLCBtYXBwaW5nPWFlcyhjb2xvcj1wb3B1bGF0aW9uX3N0YXR1cykpKw0KdGhlbWVfbWluaW1hbCgpKw0KbGFicyh0aXRsZSA9ICJDb252ZW5pZW5jZSBTdG9yZXMgaW4gTWFqb3JpdHkgV2hpdGUgYW5kIE5vbiBNYWpvcml0eSBXaGl0ZSBCYWx0aW1vcmUgTmVpZ2hib3Job29kcyIsIA0KICAgICAgIHN1YnRpdGxlID0gIkpvaG5zIEhvcGtpbnMgYW5kIEJhbHRpbW9yZSBOZWlnaGJvcmhvb2QgSW5kaWNhdG9ycyBBbGxpYW5jZSBEYXRhLCAyMDIyIiwNCiAgICAgICBjYXB0aW9uID0gIkdyYXBoaWMgYnkgTmF0YWxpZSBBZGFtcyIpDQpgYGANCg0KI2xlYWZsZXQgcmFjZSBncmFwaA0KVGhlIG5laWdoYm9yaG9vZHMgaGlnaGxpZ2h0ZWQgaW4geWVsbG93IHJlcHJlc2VudCB0aG9zZSB3aXRoIGEgbWFqb3JpdHkgd2hpdGUgcG9wdWxhdGlvbi4gVGhlIG5laWdoYm9yaG9vZHMgaW4gYmx1ZSBoYXZlIGEgbWFqb3JpdHkgbm9uLXdoaXRlIHBvcHVsYXRpb24uIA0KQSB3b3JrIGluIHByb2dyZXNzLCBtb3JlIHRvIGNvbWUuDQoNCmBgYHtyfQ0KcGFsIDwtIGNvbG9yRmFjdG9yKA0KICBwYWxldHRlID0gYygncmVkJywgJ2RhcmtncmVlbicsICdibGFjaycpLA0KICBkb21haW4gPSBiYWx0aW1vcmVfc3RvcmVzJHN0b3JlX3R5cGUNCikNCg0KbGVhZmxldCgpICU+JQ0KICBhZGRQcm92aWRlclRpbGVzKHByb3ZpZGVycyRDYXJ0b0RCLlBvc2l0cm9uKSAlPiUNCiAgYWRkUG9seWdvbnMoZGF0YT1tYWpvcml0eV93aGl0ZSwNCiAgICAgICAgICAgICAgY29sb3IgPSAoIiNmYmQwMDkiKSwNCiAgICAgICAgICAgICAgd2VpZ2h0ID0gMS41LA0KICAgICAgICAgICAgICBzbW9vdGhGYWN0b3IgPSAwLjIsDQogICAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0gMC4xLA0KICAgICAgICAgICAgICBsYWJlbCA9IG1ham9yaXR5X3doaXRlJG5laWdoYm9yaG9vZCkgJT4lIA0KICBhZGRQb2x5Z29ucyhkYXRhPW5vbl9tYWpvcml0eV93aGl0ZSwNCiAgICAgICAgICAgICAgY29sb3IgPSAoIiMxOTliZDYiKSwNCiAgICAgICAgICAgICAgd2VpZ2h0ID0gMS41LA0KICAgICAgICAgICAgICBzbW9vdGhGYWN0b3IgPSAwLjIsDQogICAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0gMC4xLA0KICAgICAgICAgICAgICBsYWJlbCA9IG5vbl9tYWpvcml0eV93aGl0ZSRuZWlnaGJvcmhvb2QpICU+JQ0KICBhZGRDaXJjbGVzKGRhdGE9YmFsdGltb3JlX3N0b3JlcywNCiAgICAgICAgICAgICB3ZWlnaHQgPSAyLA0KICAgICAgICAgICAgIGNvbG9yID0gfnBhbChzdG9yZV90eXBlKSwNCiAgICAgICAgICAgICBsYWJlbD0gcGFzdGUoIlN0b3JlIE5hbWU6IixiYWx0aW1vcmVfc3RvcmVzJG5hbWUsICJTdG9yZSBUeXBlOiIsIGJhbHRpbW9yZV9zdG9yZXMkc3RvcmVfdHlwZSkpICU+JSANCiAgICBhZGRMZWdlbmQoDQogICBwb3NpdGlvbiA9ICJib3R0b21yaWdodCIsDQogICAgcGFsID0gcGFsLA0KICAgIHZhbHVlcyA9IGJhbHRpbW9yZV9zdG9yZXMkc3RvcmVfdHlwZSwNCiAgICB0aXRsZSA9ICJCYWx0aW1vcmUgU3RvcmVzIGJ5IFR5cGUiDQogICkNCg0KDQpgYGANCiNJbmNvbWUgTGVhZmxldCBHcmFwaA0KVGhlIG5laWdoYm9yaG9vZHMgd2l0aCBhIGxvdyBpbmNvbWUgYXJlIGhpZ2hsaWdodGVkIGluIHllbGxvdyBhbmQgbmVpZ2hib3Job29kcyB3aXRoIGhpZ2ggaW5jb21lcyBhcmUgaGlnaGxpZ2h0ZWQgaW4gYmx1ZS4NCmBgYHtyfQ0KcGFsIDwtIGNvbG9yRmFjdG9yKA0KICBwYWxldHRlID0gYygncmVkJywgJ2RhcmtncmVlbicsICdibGFjaycpLA0KICBkb21haW4gPSBiYWx0aW1vcmVfc3RvcmVzJHN0b3JlX3R5cGUNCikNCmxlYWZsZXQoKSAlPiUNCiAgYWRkUHJvdmlkZXJUaWxlcyhwcm92aWRlcnMkQ2FydG9EQi5Qb3NpdHJvbikgJT4lDQogIGFkZFBvbHlnb25zKGRhdGE9bG93X2luY29tZSwNCiAgICAgICAgICAgICAgY29sb3IgPSAoIiMxOTliZDYiKSwNCiAgICAgICAgICAgICAgd2VpZ2h0ID0gMS41LA0KICAgICAgICAgICAgICBzbW9vdGhGYWN0b3IgPSAwLjIsDQogICAgICAgICAgICAgIGZpbGxPcGFjaXR5ID0gMC4xLA0KICAgICAgICAgICAgICBsYWJlbCA9IG1ham9yaXR5X3doaXRlJG5laWdoYm9yaG9vZCkgJT4lIA0KICBhZGRQb2x5Z29ucyhkYXRhPWhpZ2hfaW5jb21lLA0KICAgICAgICAgICAgICBjb2xvciA9ICgiI2ZiZDAwOSIpLA0KICAgICAgICAgICAgICB3ZWlnaHQgPSAxLjUsDQogICAgICAgICAgICAgIHNtb290aEZhY3RvciA9IDAuMiwNCiAgICAgICAgICAgICAgZmlsbE9wYWNpdHkgPSAwLjEsDQogICAgICAgICAgICAgIGxhYmVsID0gbm9uX21ham9yaXR5X3doaXRlJG5laWdoYm9yaG9vZCkgJT4lDQogIGFkZENpcmNsZXMoZGF0YT1iYWx0aW1vcmVfc3RvcmVzLA0KICAgICAgICAgICAgIHdlaWdodCA9IDIsDQogICAgICAgICAgICAgY29sb3IgPSB+cGFsKHN0b3JlX3R5cGUpLA0KICAgICAgICAgICAgIGxhYmVsPSBwYXN0ZSgiU3RvcmUgTmFtZToiLGJhbHRpbW9yZV9zdG9yZXMkbmFtZSwgIlN0b3JlIFR5cGU6IiwgYmFsdGltb3JlX3N0b3JlcyRzdG9yZV90eXBlKSkgJT4lIA0KICAgIGFkZExlZ2VuZCgNCiAgIHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IiwNCiAgICBwYWwgPSBwYWwsDQogICAgdmFsdWVzID0gYmFsdGltb3JlX3N0b3JlcyRzdG9yZV90eXBlLA0KICAgIHRpdGxlID0gIkJhbHRpbW9yZSBTdG9yZXMgYnkgVHlwZSINCiAgKQ0KDQpgYGANCg0KDQo=